<script setup lang="ts">
import { ElMessage, FormInstance } from 'element-plus';
import { reactive, ref, watch } from 'vue';
import {
  Candidate,
  Interview,
  INTERVIEW_STAGE,
  INTERVIEW_STATUS,
} from '../types/Candidate';
// 面试弹窗是否显示
const interviewFormVisible = ref(false);
// 正在编辑的面试者的
const interviewIndex = ref(-1);
// 正在编辑的面试者数据
const interviewEditRow = ref<Candidate>();
// 编辑过的面试者数据索引集合
const editIndexSet = ref<Set<number>>(new Set());
// 管理页面的面试对象接口
interface InterviewCell extends Interview {
  isEdit: boolean;
}
// 管理页面的面试者对象接口
interface CandidateRow {
  id: string; // 面试者ID
  name: string; // 面试者姓名
  resume_name: string; // 简历名称
  resume_url: string; // 简历下载地址
  stage: string; // 面试进度
  interviews: InterviewCell[]; // 面试细节
}
// 定义组件props，
const props = defineProps<{
  data?: Candidate[]; // 面试者列表
  loading?: boolean; // 是否加载中
}>();
// 面试表单
const interviewForm = reactive<{
  status: string; // 面试结果
  content: string; // 面试评价
}>({ status: '', content: '' });
// 将父组件传来的数据本地化
const localData = ref<CandidateRow[]>();
// 本地化数据备份，用于修改
const bakcupData = ref<Candidate[]>();
// 面试表单引用
const interviewFormRef = ref<FormInstance>();
// 定义组件emit事件，将更新面试者的信息传递给父组件
const emit = defineEmits<{
  (
    e: 'submit',
    data: Candidate,
    index: number,
    callback: (index: number) => void
  ): void;
}>();
// 面试表单规则
const rules = {
  status: [{ required: true, message: '请选择状态', trigger: 'blur' }],
  content: [{ required: true, message: '请输入评价', trigger: 'blur' }],
};
// 监听面试者列表数据
watch(
  () => props.data,
  (newValue) => {
    if (newValue) {
      editIndexSet.value = new Set();
      // 将父组件传入的数据在组件内部本地化
      newValue.forEach((item: Candidate) => {
        const interviewCell: InterviewCell[] = [];
        item.interviews.forEach((interview: Interview) => {
          interviewCell.push({ ...interview, isEdit: false });
        });
        localData.value?.push({
          id: item.id,
          name: item.name,
          resume_name: item.resume_name,
          resume_url: item.resume_url,
          stage: item.stage,
          interviews: interviewCell,
        });
      });
      bakcupData.value = [...newValue];
    } else {
      localData.value = [];
      bakcupData.value = [];
    }
  },
  { immediate: true }
);
// 面试进度列表
const stageList = [
  INTERVIEW_STAGE.NOT_START,
  INTERVIEW_STAGE.FIRST_ROUND,
  INTERVIEW_STAGE.SECOND_ROUND,
  INTERVIEW_STAGE.THIRD_ROUND,
  INTERVIEW_STAGE.PASS,
  INTERVIEW_STAGE.REJECT,
];
// 面试轮列表
const interviewList = [
  INTERVIEW_STAGE.FIRST_ROUND,
  INTERVIEW_STAGE.SECOND_ROUND,
  INTERVIEW_STAGE.THIRD_ROUND,
];
// 面试结果列表
const interviewStatus = [INTERVIEW_STATUS.PASS, INTERVIEW_STATUS.REJECT];
// 更新面试者信息成功回调，删除更新索引集合内对应的面试者索引数据
const successCallback = (index: number): void => {
  editIndexSet.value.delete(index);
};
// 提交面试者修改表单
const handleSubmit = (index: number) => {
  const submitInterviewList: Interview[] = [];
  if (localData.value) {
    const submitData = { ...localData.value[index] };
    submitData.interviews.forEach((item: InterviewCell) => {
      submitInterviewList.push({
        name: item.name,
        status: item.status,
        content: item.content,
      });
    });
    const subData = {
      id: submitData.id,
      name: submitData.name,
      resume_name: submitData.resume_name,
      resume_url: submitData.resume_url,
      stage: submitData.stage,
      interviews: submitInterviewList,
    };
    if (bakcupData.value) {
      bakcupData.value[index] = subData;
    }
    emit('submit', subData, index, successCallback);
  }
};
// 重置面试者更改数据
const handleReset = (index: number) => {
  if (editIndexSet.value.has(index) && localData.value && bakcupData.value) {
    const interviewCell: InterviewCell[] = [];
    bakcupData.value[index].interviews.forEach((interview: Interview) => {
      interviewCell.push({ ...interview, isEdit: false });
    });
    localData.value[index].stage = bakcupData.value[index].stage;
    localData.value[index].interviews = interviewCell;
    editIndexSet.value.delete(index);
  }
};
// 将当前面试者的面试进度更新到下一阶段
const moveToNextStage = (index: number, data: CandidateRow) => {
  const stageIndex = stageList.findIndex((item: string) => data.stage === item);
  const target = data;
  if (
    stageIndex !== -1 &&
    target.interviews.length &&
    target.interviews[stageIndex - 1].status === INTERVIEW_STATUS.START
  ) {
    ElMessage.error('当前还有进行中的面试');
  } else {
    target.stage = stageList[stageIndex + 1];
    editIndexSet.value.add(index);
    if (stageIndex >= 0 && stageIndex <= 2) {
      target.interviews.push({
        name: stageList[stageIndex + 1],
        status: INTERVIEW_STATUS.START,
        content: '',
        isEdit: false,
      });
    }
  }
};
// 编辑面试内容
const editInterview = (index: number, row: number, data: CandidateRow) => {
  interviewForm.status = '';
  interviewForm.content = '';
  interviewFormVisible.value = true;
  interviewIndex.value = index;
  interviewEditRow.value = data;
  editIndexSet.value.add(row);
};
// 提交面试表单
const submitInterviewChange = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      if (interviewEditRow.value) {
        interviewEditRow.value.interviews[interviewIndex.value].status =
          interviewForm.status;
        interviewEditRow.value.interviews[interviewIndex.value].content =
          interviewForm.content;
        interviewFormVisible.value = false;
        interviewIndex.value = -1;
        interviewEditRow.value = undefined;
      }
    } else {
      ElMessage.error('请仔细检查表单');
    }
  });
};
// 直接拒绝面试者方法
const rejectStage = (index: number, data: CandidateRow) => {
  const target = data;
  target.stage = INTERVIEW_STAGE.REJECT;
  editIndexSet.value.add(index);
};
// 按钮检测是否是合法的面试进度状态
const checkStage = (data: CandidateRow) => {
  return (
    data.stage === INTERVIEW_STAGE.PASS || data.stage === INTERVIEW_STAGE.REJECT
  );
};
// 判断提交面试者更新的按钮是否可以点击
const disableButton = (index: number) => {
  return !editIndexSet.value.has(index);
};
</script>

<template>
  <el-table
    v-loading="loading"
    :data="localData"
    border
    class="table"
    header-cell-class-name="table-header"
  >
    <el-table-column
      prop="name"
      label="姓名"
      width="100"
      align="center"
    ></el-table-column>
    <el-table-column prop="resume_name" width="150" label="简历">
      <template #default="scope">
        <el-link type="primary" :href="scope.row.resume_url" target="_blank">{{
          scope.row.resume_name
        }}</el-link>
      </template>
    </el-table-column>
    <el-table-column width="180" label="目前状态">
      <template #default="scope">
        {{ scope.row.stage }}
        <el-popconfirm
          confirm-button-text="确定"
          cancel-button-text="取消"
          icon="eli-InfoFilled"
          icon-color="red"
          title="确定将当前求职者跳转到下一阶段么？"
          @confirm="moveToNextStage(scope.$index, scope.row)"
        >
          <template #reference>
            <el-button
              type="success"
              icon="eli-Plus"
              circle
              size="small"
              :disabled="checkStage(scope.row)"
            />
          </template>
        </el-popconfirm>
        <el-popconfirm
          confirm-button-text="确定"
          cancel-button-text="取消"
          icon="eli-InfoFilled"
          icon-color="red"
          title="确定直接面试拒绝么？"
          @confirm="rejectStage(scope.$index, scope.row)"
        >
          <template #reference>
            <el-button
              type="danger"
              icon="eli-Close"
              circle
              size="small"
              :disabled="checkStage(scope.row)"
            />
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
    <el-table-column
      v-for="(item, index) in interviewList"
      :key="item"
      :label="item"
    >
      <template #default="scope">
        <el-button
          v-if="scope.row.interviews[index]?.status === INTERVIEW_STATUS.START"
          size="small"
          type="primary"
          :disabled="checkStage(scope.row)"
          @click="editInterview(Number(index), scope.$index, scope.row)"
          >面试中</el-button
        >
        <el-icon
          v-if="scope.row.interviews[index]?.status === INTERVIEW_STATUS.PASS"
          color="#67C23A"
        >
          <eli-check />
        </el-icon>
        <el-icon
          v-if="scope.row.interviews[index]?.status === INTERVIEW_STATUS.REJECT"
          color="#F56C6C"
        >
          <eli-closeBold />
        </el-icon>
        {{ scope.row.interviews[index]?.content }}
      </template>
    </el-table-column>
    <el-table-column label="操作" align="center" width="180">
      <template #default="scope">
        <el-button
          size="small"
          icon="eli-Check"
          title="提交修改"
          type="success"
          :disabled="disableButton(scope.$index)"
          @click="handleSubmit(scope.$index)"
          >提交</el-button
        >
        <el-button
          size="small"
          type="warning"
          icon="eli-RefreshLeft"
          :disabled="disableButton(scope.$index)"
          @click="handleReset(scope.$index)"
          >恢复</el-button
        >
      </template>
    </el-table-column>
  </el-table>
  <!-- 面试编辑表单对话框 -->
  <el-dialog v-model="interviewFormVisible" title="面试结果" width="50%">
    <el-form ref="interviewFormRef" :model="interviewForm" :rules="rules">
      <el-form-item label="面试结果" prop="status">
        <el-select v-model="interviewForm.status" placeholder="请选择面试结果">
          <el-option
            v-for="item in interviewStatus"
            :key="item"
            :label="item"
            :value="item"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="面试评语" prop="content">
        <el-input
          v-model="interviewForm.content"
          type="textarea"
          rows="2"
        ></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="interviewFormVisible = false">取消</el-button>
        <el-button
          type="primary"
          @click="submitInterviewChange(interviewFormRef)"
          >更新</el-button
        >
      </span>
    </template>
  </el-dialog>
</template>

<style scoed></style>
